﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0059)http://www.wangafu.net/~nickm/libevent-book/Ref4_event.html -->
<HTML xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"><HEAD><META 
content="IE=7.0000" http-equiv="X-UA-Compatible">
<TITLE></TITLE>
<META content="text/html; charset=UTF-8" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 8.00.6001.18702">
<STYLE type=text/css>P {
	
}
LI {
	
}
DT {
	
}
DD {
	
}
DIV {
	
}
PRE {
	
}
H1 {
	
}
H2 {
	
}
H3 {
	
}
H4 {
	
}
H5 {
	
}
H6 {
	
}
BODY {
	MARGIN: 1em 5%
}
A {
	COLOR: blue; TEXT-DECORATION: underline
}
A:visited {
	COLOR: fuchsia
}
EM {
	FONT-STYLE: italic; COLOR: navy
}
STRONG {
	COLOR: #083194; FONT-WEIGHT: bold
}
TT {
	COLOR: navy
}
H1 {
	LINE-HEIGHT: 1.3; MARGIN-TOP: 1.2em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd
}
H2 {
	LINE-HEIGHT: 1.3; MARGIN-TOP: 1.2em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd
}
H3 {
	LINE-HEIGHT: 1.3; MARGIN-TOP: 1.2em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd
}
H4 {
	LINE-HEIGHT: 1.3; MARGIN-TOP: 1.2em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd
}
H5 {
	LINE-HEIGHT: 1.3; MARGIN-TOP: 1.2em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd
}
H6 {
	LINE-HEIGHT: 1.3; MARGIN-TOP: 1.2em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd
}
H1 {
	BORDER-BOTTOM: silver 2px solid
}
H2 {
	BORDER-BOTTOM: silver 2px solid
}
H3 {
	BORDER-BOTTOM: silver 2px solid
}
H2 {
	PADDING-TOP: 0.5em
}
H3 {
	FLOAT: left
}
H3 + * {
	CLEAR: left
}
DIV.sectionbody {
	FONT-FAMILY: serif; MARGIN-LEFT: 0px
}
HR {
	BORDER-BOTTOM: silver 1px solid; BORDER-LEFT: silver 1px solid; BORDER-TOP: silver 1px solid; BORDER-RIGHT: silver 1px solid
}
P {
	MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.5em
}
UL {
	MARGIN-TOP: 0px
}
OL {
	MARGIN-TOP: 0px
}
LI > P {
	MARGIN-TOP: 0px
}
PRE {
	PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; PADDING-TOP: 0px
}
SPAN#author {
	FONT-FAMILY: sans-serif; COLOR: #527bbd; FONT-SIZE: 1.1em; FONT-WEIGHT: bold
}
SPAN#email {
	
}
SPAN#revnumber {
	FONT-FAMILY: sans-serif
}
SPAN#revdate {
	FONT-FAMILY: sans-serif
}
SPAN#revremark {
	FONT-FAMILY: sans-serif
}
DIV#footer {
	MARGIN-TOP: 4em; FONT-FAMILY: sans-serif; FONT-SIZE: small; BORDER-TOP: silver 2px solid; PADDING-TOP: 0.5em
}
DIV#footer-text {
	PADDING-BOTTOM: 0.5em; FLOAT: left
}
DIV#footer-badges {
	PADDING-BOTTOM: 0.5em; FLOAT: right
}
DIV#preamble {
	MARGIN-TOP: 1.5em; MARGIN-BOTTOM: 1.5em
}
DIV.tableblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.imageblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.exampleblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.verseblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.quoteblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.literalblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.listingblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.sidebarblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.admonitionblock {
	MARGIN-TOP: 1em; MARGIN-BOTTOM: 1.5em
}
DIV.admonitionblock {
	MARGIN-TOP: 2em; MARGIN-BOTTOM: 2em; COLOR: #606060; MARGIN-RIGHT: 10%
}
DIV.content {
	PADDING-BOTTOM: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; PADDING-TOP: 0px
}
DIV.title {
	TEXT-ALIGN: left; MARGIN-TOP: 1em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd; FONT-WEIGHT: bold
}
CAPTION.title {
	TEXT-ALIGN: left; MARGIN-TOP: 1em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd; FONT-WEIGHT: bold
}
DIV.title + * {
	MARGIN-TOP: 0px
}
TD DIV.title:first-child {
	MARGIN-TOP: 0em
}
DIV.content DIV.title:first-child {
	MARGIN-TOP: 0em
}
DIV.content + DIV.title {
	MARGIN-TOP: 0em
}
DIV.sidebarblock > DIV.content {
	BORDER-BOTTOM: silver 1px solid; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 0.5em; PADDING-LEFT: 0.5em; PADDING-RIGHT: 0.5em; BACKGROUND: #ffffee; BORDER-TOP: silver 1px solid; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 0.5em
}
DIV.listingblock > DIV.content {
	BORDER-BOTTOM: silver 1px solid; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 0.5em; PADDING-LEFT: 0.5em; PADDING-RIGHT: 0.5em; BACKGROUND: #f4f4f4; BORDER-TOP: silver 1px solid; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 0.5em
}
DIV.quoteblock {
	BORDER-LEFT: #dddddd 5px solid; PADDING-LEFT: 1em; COLOR: #777777; MARGIN-LEFT: 1em; MARGIN-RIGHT: 10%
}
DIV.verseblock {
	BORDER-LEFT: #dddddd 5px solid; PADDING-LEFT: 1em; COLOR: #777777; MARGIN-LEFT: 1em; MARGIN-RIGHT: 10%
}
DIV.quoteblock > DIV.attribution {
	TEXT-ALIGN: right; PADDING-TOP: 0.5em
}
DIV.verseblock > DIV.content {
	WHITE-SPACE: pre
}
DIV.verseblock > DIV.attribution {
	TEXT-ALIGN: left; PADDING-TOP: 0.75em
}
DIV.verseblock + DIV.attribution {
	TEXT-ALIGN: left
}
DIV.admonitionblock .icon {
	PADDING-RIGHT: 0.5em; COLOR: #527bbd; FONT-SIZE: 1.1em; VERTICAL-ALIGN: top; FONT-WEIGHT: bold; TEXT-DECORATION: underline
}
DIV.admonitionblock TD.content {
	BORDER-LEFT: #dddddd 3px solid; PADDING-LEFT: 0.5em
}
DIV.exampleblock > DIV.content {
	BORDER-LEFT: #dddddd 3px solid; PADDING-LEFT: 0.5em
}
DIV.imageblock DIV.content {
	PADDING-LEFT: 0px
}
SPAN.image IMG {
	BORDER-BOTTOM-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-TOP-STYLE: none; BORDER-LEFT-STYLE: none
}
A.image:visited {
	COLOR: white
}
DL {
	MARGIN-TOP: 0.8em; MARGIN-BOTTOM: 0.8em
}
DT {
	FONT-STYLE: normal; MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0px; COLOR: navy
}
DD > *:first-child {
	MARGIN-TOP: 0.1em
}
UL {
	LIST-STYLE-POSITION: outside
}
OL {
	LIST-STYLE-POSITION: outside
}
OL.arabic {
	LIST-STYLE-TYPE: decimal
}
OL.loweralpha {
	LIST-STYLE-TYPE: lower-alpha
}
OL.upperalpha {
	LIST-STYLE-TYPE: upper-alpha
}
OL.lowerroman {
	LIST-STYLE-TYPE: lower-roman
}
OL.upperroman {
	LIST-STYLE-TYPE: upper-roman
}
DIV.compact UL {
	MARGIN-TOP: 0.1em; MARGIN-BOTTOM: 0.1em
}
DIV.compact OL {
	MARGIN-TOP: 0.1em; MARGIN-BOTTOM: 0.1em
}
DIV.compact P {
	MARGIN-TOP: 0.1em; MARGIN-BOTTOM: 0.1em
}
DIV.compact P {
	MARGIN-TOP: 0.1em; MARGIN-BOTTOM: 0.1em
}
DIV.compact DIV {
	MARGIN-TOP: 0.1em; MARGIN-BOTTOM: 0.1em
}
DIV.compact DIV {
	MARGIN-TOP: 0.1em; MARGIN-BOTTOM: 0.1em
}
DIV.tableblock > TABLE {
	BORDER-BOTTOM: #527bbd 3px solid; BORDER-LEFT: #527bbd 3px solid; BORDER-TOP: #527bbd 3px solid; BORDER-RIGHT: #527bbd 3px solid
}
THEAD {
	FONT-FAMILY: sans-serif; FONT-WEIGHT: bold
}
P.header.table {
	FONT-FAMILY: sans-serif; FONT-WEIGHT: bold
}
TFOOT {
	FONT-WEIGHT: bold
}
TD > DIV.verse {
	WHITE-SPACE: pre
}
P.table {
	MARGIN-TOP: 0px
}
DIV.tableblock > TABLE[frame='void'] {
	BORDER-BOTTOM-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-TOP-STYLE: none; BORDER-LEFT-STYLE: none
}
DIV.tableblock > TABLE[frame='hsides'] {
	BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none
}
DIV.tableblock > TABLE[frame='vsides'] {
	BORDER-BOTTOM-STYLE: none; BORDER-TOP-STYLE: none
}
DIV.hdlist {
	MARGIN-TOP: 0.8em; MARGIN-BOTTOM: 0.8em
}
DIV.hdlist TR {
	PADDING-BOTTOM: 15px
}
DT.strong.hdlist1 {
	FONT-WEIGHT: bold
}
TD.strong.hdlist1 {
	FONT-WEIGHT: bold
}
TD.hdlist1 {
	FONT-STYLE: normal; PADDING-RIGHT: 0.8em; COLOR: navy; VERTICAL-ALIGN: top
}
TD.hdlist2 {
	VERTICAL-ALIGN: top
}
DIV.compact.hdlist TR {
	PADDING-BOTTOM: 0px; MARGIN: 0px
}
.comment {
	BACKGROUND: yellow
}
.footnote {
	FONT-SIZE: 0.8em
}
.footnoteref {
	FONT-SIZE: 0.8em
}
SPAN.footnote {
	VERTICAL-ALIGN: super
}
SPAN.footnoteref {
	VERTICAL-ALIGN: super
}
#footnotes {
	PADDING-BOTTOM: 0px; MARGIN: 20px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; PADDING-TOP: 7px
}
#footnotes DIV.footnote {
	MARGIN: 0px 0px 5px
}
#footnotes HR {
	BORDER-BOTTOM-STYLE: none; MIN-WIDTH: 100px; TEXT-ALIGN: left; BORDER-RIGHT-STYLE: none; WIDTH: 20%; HEIGHT: 1px; MARGIN-LEFT: 0px; BORDER-LEFT-STYLE: none; BORDER-TOP: silver 1px solid
}

@media Print    
{
DIV#footer-badges {
	DISPLAY: none
}
    }
DIV#toc {
	MARGIN-BOTTOM: 2.5em
}
DIV#toctitle {
	MARGIN-TOP: 1em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.1em; COLOR: #527bbd; FONT-SIZE: 1.1em; FONT-WEIGHT: bold
}
DIV.toclevel1 {
	MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
DIV.toclevel2 {
	MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
DIV.toclevel3 {
	MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
DIV.toclevel4 {
	MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
DIV.toclevel2 {
	MARGIN-LEFT: 2em; FONT-SIZE: 0.9em
}
DIV.toclevel3 {
	MARGIN-LEFT: 4em; FONT-SIZE: 0.9em
}
DIV.toclevel4 {
	MARGIN-LEFT: 6em; FONT-SIZE: 0.9em
}
DIV.sidebar-content {
	BORDER-BOTTOM: silver 1px solid; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 0.5em; PADDING-LEFT: 0.5em; PADDING-RIGHT: 0.5em; BACKGROUND: #ffffee; BORDER-TOP: silver 1px solid; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 0.5em
}
DIV.sidebar-title {
	MARGIN-TOP: 0em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd; FONT-WEIGHT: bold
}
DIV.image-title {
	MARGIN-TOP: 0em; FONT-FAMILY: sans-serif; MARGIN-BOTTOM: 0.5em; COLOR: #527bbd; FONT-WEIGHT: bold
}
DIV.listingblock DIV.content {
	BORDER-BOTTOM: silver 1px solid; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 0.5em; PADDING-LEFT: 0.5em; PADDING-RIGHT: 0.5em; BACKGROUND: #f4f4f4; BORDER-TOP: silver 1px solid; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 0.5em
}
DIV.quoteblock-attribution {
	TEXT-ALIGN: right; PADDING-TOP: 0.5em
}
DIV.verseblock-content {
	WHITE-SPACE: pre
}
DIV.verseblock-attribution {
	TEXT-ALIGN: left; PADDING-TOP: 0.75em
}
DIV.exampleblock-content {
	BORDER-LEFT: #dddddd 3px solid; PADDING-LEFT: 0.5em
}
DIV#toc A:visited {
	COLOR: blue
}
</STYLE>

<SCRIPT type=text/javascript>
/*<![CDATA[*/
window.onload = function(){asciidoc.footnotes();}
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  var cont = document.getElementById("content");
  var noteholder = document.getElementById("footnotes");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      // Use [\s\S] in place of . so multi-line matches work.
      // Because JavaScript has no s (dotall) regex flag.
      note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      spans[i].innerHTML =
        "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
        "' title='View footnote' class='footnote'>" + n + "</a>]";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
}

}
/*]]>*/
</SCRIPT>
</HEAD>
<BODY>
<DIV id=header></DIV>
<DIV id=content>
<DIV class=quoteblock>
<DIV class=quoteblock-content>
<DIV class=paragraph>
<P>These documents are Copyright (c) 2009-2010 by Nick Mathewson, and are made 
available under the Creative Commons Attribution-Noncommercial-Share Alike 
license, version 3.0. Future versions may be made available under a less 
restrictive license.</P></DIV>
<DIV class=paragraph>
<P>Additionally, the source code examples in these documents are also licensed 
under the so-called "3-Clause" or "Modified" BSD license. See <A 
href="http://www.wangafu.net/~nickm/libevent-book/license_bsd.html">the 
license_bsd file</A> distributed with these documents for the full 
terms.</P></DIV>
<DIV class=paragraph>
<P>For the latest version of this document, see <A 
href="http://www.wangafu.net/~nickm/libevent-book/TOC.html">http://www.wangafu.net/~nickm/libevent-book/TOC.html</A></P></DIV>
<DIV class=paragraph>
<P>To get the source for the latest version of this document, install git and 
run "git clone git://github.com/nmathewson/libevent-book.git"</P></DIV></DIV>
<DIV class=quoteblock-attribution></DIV></DIV>
<H2 id=_working_with_events>Working with events</H2>
<DIV class=sectionbody>
<DIV class=paragraph>
<P>Libevent’s basic unit of operation is the <EM>event</EM>. Every event 
represents a set of conditions, including:</P></DIV>
<DIV class=ulist>
<UL>
  <LI>
  <P>A file descriptor being ready to read from or write to. </P>
  <LI>
  <P>A file descriptor <EM>becoming</EM> ready to read from or write to 
  (Edge-triggered IO only). </P>
  <LI>
  <P>A timeout expiring. </P>
  <LI>
  <P>A signal occurring. </P>
  <LI>
  <P>A user-triggered event. </P></LI></UL></DIV>
<DIV class=paragraph>
<P>Events have similar lifecycles. Once you call a Libevent function to set up 
an event and associate it with an event base, it becomes 
<STRONG>initialized</STRONG>. At this point, you can <EM>add</EM>, which makes 
it <STRONG>pending</STRONG> in the base. When the event is pending, if the 
conditions that would trigger an event occur (e.g., its file descriptor changes 
state or its timeout expires), the event becomes <STRONG>active</STRONG>, and 
its (user-provided) callback function is run. If the event is configured 
<STRONG>persistent</STRONG>, it remains pending. If it is not persistent, it 
stops being pending when its callback runs. You can make a pending event 
non-pending by <EM>deleting</EM> it, and you can <EM>add</EM> a non-pending 
event to make it pending again.</P></DIV>
<H3 id=_constructing_event_objects>Constructing event objects</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>To create a new event, use the event_new() interface.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT>#define EV_TIMEOUT      0x01
#define EV_READ         0x02
#define EV_WRITE        0x04
#define EV_SIGNAL       0x08
#define EV_PERSIST      0x10
#define EV_ET           0x20

<STRONG>typedef</STRONG> <STRONG>void</STRONG> (*event_callback_fn)(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);

<STRONG>struct</STRONG> event *event_new(<STRONG>struct</STRONG> event_base *base, evutil_socket_t fd,
    <STRONG>short</STRONG> what, event_callback_fn cb,
    <STRONG>void</STRONG> *arg);

<STRONG>void</STRONG> event_free(<STRONG>struct</STRONG> event *event);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The event_new() function tries to allocate and construct a new event for use 
with <EM>base</EM>. The <EM>what</EM> argument is a set of the flags listed 
above. (Their semantics are described below.) If <EM>fd</EM> is nonnegative, it 
is the file that we’ll observe for read or write events. When the event is 
active, Libevent will invoke the provided <EM>cb</EM> function, passing it as 
arguments: the file descriptor <EM>fd</EM>, a bitfield of <EM>all</EM> the 
events that triggered, and the value that was passed in for <EM>arg</EM> when 
the function was constructed.</P></DIV>
<DIV class=paragraph>
<P>On an internal error, or invalid arguments, event_new() will return 
NULL.</P></DIV>
<DIV class=paragraph>
<P>All new events are initialized and non-pending. To make an event pending, 
call event_add() (documented below).</P></DIV>
<DIV class=paragraph>
<P>To deallocate an event, call event_free(). It is safe to call event_free() on 
an event that is pending or active: doing so makes the event non-pending and 
inactive before deallocating it.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT>#include &lt;event2/event.h&gt;

<STRONG>void</STRONG> cb_func(evutil_socket_t fd, <STRONG>short</STRONG> what, <STRONG>void</STRONG> *arg)
{
        <STRONG>const</STRONG> <STRONG>char</STRONG> *data = arg;
        printf("Got an event on socket %d:%s%s%s%s [%s]",
            (<STRONG>int</STRONG>) fd,
            (what&amp;EV_TIMEOUT) ? " timeout" : "",
            (what&amp;EV_READ)    ? " read" : "",
            (what&amp;EV_WRITE)   ? " write" : "",
            (what&amp;EV_SIGNAL)  ? " signal" : "",
            data);
}

<STRONG>void</STRONG> main_loop(evutil_socket_t fd1, evutil_socket_t fd2)
{
        <STRONG>struct</STRONG> event *ev1, *ev2;
        <STRONG>struct</STRONG> timeval five_seconds = {5,0};
        <STRONG>struct</STRONG> event_base *base = event_base_new();

<I>        /* The caller has already set up fd1, fd2 somehow, and make them</I>
<I>           nonblocking. */</I>

        ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, cb_func,
           (<STRONG>char</STRONG>*)"Reading event");
        ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, cb_func,
           (<STRONG>char</STRONG>*)"Writing event");

        event_add(ev1, &amp;five_seconds);
        event_add(ev2, NULL);
        event_base_dispatch(base);
}</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The above functions are defined in &lt;event2/event.h&gt;, and first appeared 
in Libevent 2.0.1-alpha. The event_callback_fn type first appeared as a typedef 
in Libevent 2.0.4-alpha.</P></DIV>
<H4 id=_the_event_flags>The event flags</H4>
<DIV class=dlist>
<DL>
  <DT class=hdlist1>EV_TIMEOUT 
  <DD>
  <P>This flag indicates an event that becomes active after a timeout elapses. 
  </P>
  <DIV class=literalblock>
  <DIV class=content><PRE><TT>The EV_TIMEOUT flag is ignored when constructing an event: you
can either set a timeout when you add the event, or not.  It is
set in the 'what' argument to the callback function when a timeout
has occurred.</TT></PRE></DIV></DIV>
  <DT class=hdlist1>EV_READ 
  <DD>
  <P>This flag indicates an event that becomes active when the provided file 
  descriptor is ready for reading. </P>
  <DT class=hdlist1>EV_WRITE 
  <DD>
  <P>This flag indicates an event that becomes active when the provided file 
  descriptor is ready for writing. </P>
  <DT class=hdlist1>EV_SIGNAL 
  <DD>
  <P>Used to implement signal detection. See "Constructing signal events" below. 
  </P>
  <DT class=hdlist1>EV_PERSIST 
  <DD>
  <P>Indicates that the event is <EM>persistent</EM>. See "About Event 
  Persistence" below. </P>
  <DT class=hdlist1>EV_ET 
  <DD>
  <P>Indicates that the event should be edge-triggered, if the underlying 
  event_base backend supports edge-triggered events. This affects the semantics 
  of EV_READ and EV_WRITE. </P></DD></DL></DIV>
<DIV class=paragraph>
<P>Since Libevent 2.0.1-alpha, any number of events may be pending for the same 
conditions at the same time. For example, you may have two events that will 
become active if a given fd becomes ready to read. The order in which their 
callbacks are run is undefined.</P></DIV>
<DIV class=paragraph>
<P>These flags are defined in &lt;event2/event.h&gt;. All have existed since 
before Libevent 1.0, except for EV_ET, which was introduced in Libevent 
2.0.1-alpha.</P></DIV>
<H4 id=_about_event_persistence>About Event Persistence</H4>
<DIV class=paragraph>
<P>By default, whenever a pending event becomes active (because its fd is ready 
to read or write, or because its timeout expires), it becomes non-pending right 
before its callback is executed. Thus, if you want to make the event pending 
again, you can call event_add() on it again from inside the callback 
function.</P></DIV>
<DIV class=paragraph>
<P>If the EV_PERSIST flag is set on an event, however, the event is 
<EM>persistent.</EM> This means that event remains pending even when its 
callback is activated. If you want to make it non-pending from within its 
callback, you can call event_del() on it.</P></DIV>
<DIV class=paragraph>
<P>The timeout on a persistent event resets whenever the event’s callback runs. 
Thus, if you have an event with flags EV_READ|EV_PERSIST and a timeout of five 
seconds, the event will become active:</P></DIV>
<DIV class=ulist>
<UL>
  <LI>
  <P>Whenever the socket is ready for reading. </P>
  <LI>
  <P>Whenever five seconds have passed since the event last became active. 
  </P></LI></UL></DIV>
<H4 id=_timeout_only_events>Timeout-only events</H4>
<DIV class=paragraph>
<P>As a convenience, there are a set of macros beginning with evtimer_ that you 
can use in place of the event_* calls to allocate and manipulate pure-timeout 
events. Using these macros provides no benefit beyond improving the clarity of 
your code.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT>#define evtimer_new(base, callback, arg) \
    event_new((base), -1, 0, (callback), (arg))
#define evtimer_add(ev, tv) \
    event_add((ev),(tv))
#define evtimer_del(ev) \
    event_del(ev)
#define evtimer_pending(ev, what, tv_out) \
    event_pending((ev), (what), (tv_out))</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>These macros have been present since Libevent 0.6, except for evtimer_new(), 
which first appeared in Libevent 2.0.1-alpha.</P></DIV>
<H4 id=_constructing_signal_events>Constructing signal events</H4>
<DIV class=paragraph>
<P>Libevent can also watch for POSIX-style signals. To construct a handler for a 
signal, use:</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT>#define evsignal_new(base, signum, callback, arg) \
    event_new(base, signum, EV_SIGNAL|EV_PERSIST, cb, arg)</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The arguments are as for event_new, except that we provide a signal number 
instead of a file descriptor.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT><STRONG>struct</STRONG> event *hup_event;
<STRONG>struct</STRONG> event_base *base = event_base_new();

<I>/* call sighup_function on a HUP signal */</I>
hup_event = evsignal_new(base, SIGHUP, sighup_function, NULL);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>Note that signal callbacks are run in the event loop after the signal occurs, 
so it is safe for them to call functions that you are not supposed to call from 
a regular POSIX signal handler.</P></DIV>
<DIV class=admonitionblock>
<TABLE>
  <TBODY>
  <TR>
    <TD class=icon>
      <DIV class=title>Warning</DIV></TD>
    <TD class=content>Don’t set a timeout on a signal event. It might not be 
      supported. [FIXME: is this true?]</TD></TR></TBODY></TABLE></DIV>
<DIV class=paragraph>
<P>There are also a set of convenience macros you can use when working with 
signal events.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT>#define evsignal_add(ev, tv) \
    event_add((ev),(tv))
#define evsignal_del(ev) \
    event_del(ev)
#define evsignal_pending(ev, what, tv_out) \
    event_pending((ev), (what), (tv_out))</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The evsignal_* macros have been present since Libevent 2.0.1-alpha. Prior 
versions called them signal_add(), signal_del(), and so on.</P></DIV>
<H5 id=_caveats_when_working_with_signals>Caveats when working with signals</H5>
<DIV class=paragraph>
<P>With current versions of Libevent, with most backends, only one event_base 
per process at a time can be listening for signals. If you add signal events to 
two event_bases at once ---even if the signals are different!--- only one 
event_base will receive signals.</P></DIV>
<DIV class=paragraph>
<P>The kqueue backend does not have this limitation.</P></DIV>
<H4 id=_setting_up_events_without_heap_allocation>Setting up events without 
heap-allocation</H4>
<DIV class=paragraph>
<P>For performance and other reasons, some people like to allocate events as a 
part of a larger structure. For each use of the event, this saves 
them:</P></DIV>
<DIV class=ulist>
<UL>
  <LI>
  <P>The memory allocator overhead for allocating a small object on the heap. 
  </P>
  <LI>
  <P>The time overhead for dereferencing the pointer to the struct event. </P>
  <LI>
  <P>The time overhead from a possible additional cache miss if the event is not 
  already in the cache. </P></LI></UL></DIV>
<DIV class=paragraph>
<P>Using this method risks breaking binary compatibility with other versions of 
of Libevent, which may have different sizes for the event structure.</P></DIV>
<DIV class=paragraph>
<P>These are <EM>very</EM> small costs, and do not matter for most applications. 
You should just stick to using event_new() unless you <STRONG>know</STRONG> that 
you’re incurring a significant performance penalty for heap-allocating your 
events. Using event_assign() can cause hard-to-diagnose errors with future 
versions of Libevent if they use a larger event structure than the one you’re 
building with.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>int</STRONG> event_assign(<STRONG>struct</STRONG> event *event, <STRONG>struct</STRONG> event_base *base,
    evutil_socket_t fd, <STRONG>short</STRONG> what,
    <STRONG>void</STRONG> (*callback)(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *), <STRONG>void</STRONG> *arg);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>All the arguments of event_assign() are as for event_new(), except for the 
<EM>event</EM> argument, which must point to an uninitialized event. It returns 
0 on success, and -1 on an internal error or bad arguments.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT>#include &lt;event2/event.h&gt;
<I>/* Watch out!  Including event_struct.h means that your code will not</I>
<I> * be binary-compatible with future versions of Libevent. */</I>
#include &lt;event2/event_struct.h&gt;
#include &lt;stdlib.h&gt;

<STRONG>struct</STRONG> event_pair {
         evutil_socket_t fd;
         <STRONG>struct</STRONG> event read_event;
         <STRONG>struct</STRONG> event write_event;
};
<STRONG>void</STRONG> readcb(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);
<STRONG>void</STRONG> writecb(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);
<STRONG>struct</STRONG> event_pair *event_pair_new(<STRONG>struct</STRONG> event_base *base, evutil_socket_t fd)
{
        <STRONG>struct</STRONG> event_pair *p = malloc(<STRONG>sizeof</STRONG>(<STRONG>struct</STRONG> event_pair));
        <STRONG>if</STRONG> (!p) <STRONG>return</STRONG> NULL;
        p-&gt;fd = fd;
        event_assign(&amp;p-&gt;read_event, base, fd, EV_READ|EV_PERSIST, readcb, p);
        event_assign(&amp;p-&gt;read_event, base, fd, EV_WRITE|EV_PERSIST, writecb, p);
        <STRONG>return</STRONG> p;
}</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>You can also use event_assign() to initialize stack-allocated or statically 
allocated events.</P></DIV>
<DIV class=paragraph>
<DIV class=title>WARNING</DIV>
<P>Never call event_assign() on an event that is already pending in an event 
base. Doing so can lead to extremely hard-to-diagnose errors. If the event is 
already initialized and pending, call event_del() on it <STRONG>before</STRONG> 
you call event_assign() on it again.</P></DIV>
<DIV class=paragraph>
<P>There are convenience macros you can use to event_assign() a timeout-only or 
a signal event:</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT>#define evtimer_assign(event, base, callback, arg) \
    event_assign(event, base, -1, 0, callback, arg)
#define evsignal_assign(event, base, signum, callback, arg) \
    event_assign(event, base, signum, EV_SIGNAL|EV_PERSIST, callback, arg)</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>If you need to use event_assign() <STRONG>and</STRONG> retain binary 
compatibility with future versions of Libevent, you can ask the Libevent library 
to tell you at runtime how large a <EM>struct event</EM> should be:</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT>size_t event_get_struct_event_size(<STRONG>void</STRONG>);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>This function returns the number of bytes you need to set aside for a struct 
event. As before, you should only be using this function if you know that 
heap-allocation is actually a significant problem in your program, since it can 
make your code much harder to read and write.</P></DIV>
<DIV class=paragraph>
<P>Note that event_get_struct_event_size() may in the future give you a value 
<EM>smaller</EM> than <EM>sizeof(struct event)</EM>. If this happens, it means 
that any extra bytes at the end of <EM>struct event</EM> are only padding bytes 
reserved for use by a future version of Libevent.</P></DIV>
<DIV class=paragraph>
<P>Here’s the same example as above, but instead of relying on the size of 
<EM>struct event</EM> from event_struct.h, we use event_get_struct_size() to use 
the correct size at runtime.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT>#include &lt;event2/event.h&gt;
#include &lt;stdlib.h&gt;

<I>/* When we allocate an event_pair in memory, we'll actually allocate</I>
<I> * more space at the end of the structure.  We define some macros</I>
<I> * to make accessing those events less error-prone. */</I>
<STRONG>struct</STRONG> event_pair {
         evutil_socket_t fd;
};

<I>/* Macro: yield the struct event 'offset' bytes from the start of 'p' */</I>
#define EVENT_AT_OFFSET(p, offset) \
            ((<STRONG>struct</STRONG> event*) ( ((<STRONG>char</STRONG>*)(p)) + (offset) ))
<I>/* Macro: yield the read event of an event_pair */</I>
#define READEV_PTR(pair) \
            EVENT_AT_OFFSET((pair), <STRONG>sizeof</STRONG>(<STRONG>struct</STRONG> event_pair))
<I>/* Macro: yield the write event of an event_pair */</I>
#define WRITEEV_PTR(pair) \
            EVENT_AT_OFFSET((pair), \
                <STRONG>sizeof</STRONG>(<STRONG>struct</STRONG> event_pair)+event_get_struct_event_size())

<I>/* Macro: yield the actual size to allocate for an event_pair */</I>
#define EVENT_PAIR_SIZE() \
            (<STRONG>sizeof</STRONG>(<STRONG>struct</STRONG> event_pair)+2*event_get_struct_event_size())

<STRONG>void</STRONG> readcb(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);
<STRONG>void</STRONG> writecb(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);
<STRONG>struct</STRONG> event_pair *event_pair_new(<STRONG>struct</STRONG> event_base *base, evutil_socket_t fd)
{
        <STRONG>struct</STRONG> event_pair *p = malloc(EVENT_PAIR_SIZE());
        <STRONG>if</STRONG> (!p) <STRONG>return</STRONG> NULL;
        p-&gt;fd = fd;
        event_assign(READEV_PTR(p), base, fd, EV_READ|EV_PERSIST, readcb, p);
        event_assign(WRITEEV_PTR(p), base, fd, EV_WRITE|EV_PERSIST, writecb, p);
        <STRONG>return</STRONG> p;
}</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The event_assign() function defined in &lt;event2/event.h&gt;. It has existed 
since Libevent 2.0.1-alpha. It has returned an int since 2.0.3-alpha; 
previously, it returned void. The event_get_struct_event_size() function was 
introduced in Libevent 2.0.4-alpha. The event structure itself is defined in 
&lt;event2/event_struct.h&gt;.</P></DIV>
<H3 id=_making_events_pending_and_non_pending>Making events pending and 
non-pending</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>Once you have constructed an event, it won’t actually do anything until you 
have made it <EM>pending</EM> by adding it. You do this with 
event_add:</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>int</STRONG> event_add(<STRONG>struct</STRONG> event *ev, <STRONG>const</STRONG> <STRONG>struct</STRONG> timeval *tv);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>Calling event_add on a non-pending event makes it pending in its configured 
base. The function returns 0 on success, and -1 on failure. If <EM>tv</EM> is 
NULL, the event is added with no timeout. Otherwise, <EM>tv</EM> is the size of 
the timeout in seconds and microseconds.</P></DIV>
<DIV class=paragraph>
<P>If you call event_add() on an event that is <EM>already</EM> pending, it will 
leave it pending, and reschedule it with the provided timeout.</P></DIV>
<DIV class=admonitionblock>
<TABLE>
  <TBODY>
  <TR>
    <TD class=icon>
      <DIV class=title>Note</DIV></TD>
    <TD class=content>Do not set <EM>tv</EM> to the time at which you want the 
      timeout to run. If you say "tv→tv_sec = time(NULL)+10;" on 1 January 2010, 
      your timeout will wait 40 years, not 10 seconds.</TD></TR></TBODY></TABLE></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>int</STRONG> event_del(<STRONG>struct</STRONG> event *ev);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>Calling event_del on an initialized event makes it non-pending and 
non-active. If the event was not pending or active, there is no effect. The 
return value is 0 on success, -1 on failure.</P></DIV>
<DIV class=admonitionblock>
<TABLE>
  <TBODY>
  <TR>
    <TD class=icon>
      <DIV class=title>Note</DIV></TD>
    <TD class=content>If you delete an event after it becomes active but 
      before its callback has a chance to execute, the callback will not be 
      executed.</TD></TR></TBODY></TABLE></DIV>
<DIV class=paragraph>
<P>These functions are defined in &lt;event2/event.h&gt;; they have existed 
since Libevent 0.1.</P></DIV>
<H3 id=_events_with_priorities>Events with priorities</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>When multiple events trigger at the same time, Libevent does not define any 
order with respect to when their callbacks will be executed. You can define some 
events as more important than others by using priorities.</P></DIV>
<DIV class=paragraph>
<P>As discussed in an earlier section, each event_base has one or more priority 
values associated with it. Before adding an event to the event_base, but after 
initializing it, you can set its priority.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>int</STRONG> event_priority_set(<STRONG>struct</STRONG> event *event, <STRONG>int</STRONG> priority);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The priority of the event is a number between 0 and the number of priorities 
in an event_base, minus 1. The function returns 0 on success, and -1 on 
failure.</P></DIV>
<DIV class=paragraph>
<P>When multiple events of multiple priorities become active, the low-priority 
events are not run. Instead, Libevent runs the high priority events, then checks 
for events again. Only when no high-priority events are active are the 
low-priority events run.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT>#include &lt;event2/event.h&gt;

<STRONG>void</STRONG> read_cb(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);
<STRONG>void</STRONG> write_cb(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);

<STRONG>void</STRONG> main_loop(evutil_socket_t fd)
{
  <STRONG>struct</STRONG> event *important, *unimportant;
  <STRONG>struct</STRONG> event_base *base;

  base = event_base_new();
  event_base_priority_init(base, 2);
<I>  /* Now base has priority 0, and priority 1 */</I>
  important = event_new(base, fd, EV_WRITE|EV_PERSIST, write_cb, NULL);
  unimportant = event_new(base, fd, EV_READ|EV_PERSIST, read_cb, NULL);
  event_priority_set(important, 0);
  event_priority_set(unimportant, 1);

<I>  /* Now, whenever the fd is ready for writing, the write callback will</I>
<I>     happen before the read callback.  The read callback won't happen at</I>
<I>     all until the write callback is no longer active. */</I>
}</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>When you do not set the priority for an event, the default is the number of 
queues in the event base, divided by 2.</P></DIV>
<DIV class=paragraph>
<P>This function is declared in &lt;event2/event.h&gt;. It has existed since 
Libevent 1.0.</P></DIV>
<H3 id=_inspecting_event_status>Inspecting event status</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>Sometimes you want to tell whether an event has been added, and check what it 
refers to.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>int</STRONG> event_pending(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *ev, <STRONG>short</STRONG> what, <STRONG>struct</STRONG> timeval *tv_out);

#define event_get_signal(ev) /* ... */
evutil_socket_t event_get_fd(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *ev);
<STRONG>struct</STRONG> event_base *event_get_base(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *ev);
<STRONG>short</STRONG> event_get_events(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *ev);
event_callback_fn event_get_callback(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *ev);
<STRONG>void</STRONG> *event_get_callback_arg(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *ev);

<STRONG>void</STRONG> event_get_assignment(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *event,
        <STRONG>struct</STRONG> event_base **base_out,
        evutil_socket_t *fd_out,
        <STRONG>short</STRONG> *events_out,
        event_callback_fn *callback_out,
        <STRONG>void</STRONG> **arg_out);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The event_pending function determines whether the given event is pending or 
active. If it is, and any of the flags EV_READ, EV_WRITE, EV_SIGNAL, and 
EV_TIMEOUT are set in the <EM>what</EM> argument, the function returns all of 
the flags that the event is currently pending or active on. If <EM>tv_out</EM> 
is provided, and EV_TIMEOUT is set in <EM>what</EM>, and the event is currently 
pending or active on a timeout, then <EM>tv_out</EM> is set to hold the time 
when the event’s timeout will expire.</P></DIV>
<DIV class=paragraph>
<P>The event_get_fd() and event_get_signal() functions return the configured 
file descriptor or signal number for an event. The event_get_base() function 
returns its configured event_base. The event_get_events() function returns the 
event flags (EV_READ, EV_WRITE, etc) of the event. The event_get_callback() and 
event_get_callback_arg() functions return the callback function and argument 
pointer.</P></DIV>
<DIV class=paragraph>
<P>The event_get_assignment() function copies all of the assigned fields of the 
event into the provided pointers. If any of the pointers is NULL, it is 
ignored.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT>#include &lt;event2/event.h&gt;
#include &lt;stdio.h&gt;

<I>/* Change the callback and callback_arg of 'ev', which must not be</I>
<I> * pending. */</I>
<STRONG>int</STRONG> replace_callback(<STRONG>struct</STRONG> event *ev, event_callback_fn new_callback,
    <STRONG>void</STRONG> *new_callback_arg)
{
    <STRONG>struct</STRONG> event_base *base;
    evutil_socket_t fd;
    <STRONG>short</STRONG> events;

    <STRONG>int</STRONG> pending;

    pending = event_pending(ev, EV_READ|EV_WRITE|EV_SIGNAL|EV_TIMEOUT,
                            NULL);
    <STRONG>if</STRONG> (pending) {
<I>        /* We want to catch this here so that we do not re-assign a</I>
<I>         * pending event.  That would be very very bad. */</I>
        fprintf(stderr,
                "Error! replace_callback called on a pending event!\n");
        <STRONG>return</STRONG> -1;
    }

    event_get_assignment(ev, &amp;base, &amp;fd, &amp;events,
                         NULL /* ignore old callback */ ,
                         NULL /* ignore old callback argument */);

    event_assign(ev, base, fd, events, new_callback, new_callback_arg);
    <STRONG>return</STRONG> 0;
}</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>These functions are declared in &lt;event2/event.h&gt;. The event_pending() 
function has existed since Libevent 0.1. Libevent 2.0.1-alpha introduced 
event_get_fd() and event_get_signal(). Libevent 2.0.2-alpha introduced 
event_get_base(). The others were new in Libevent 2.0.4-alpha.</P></DIV>
<H3 id=_configuring_one_off_events>Configuring one-off events</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>If you don’t need to add an event more than once, or delete it once it has 
been added, and it doesn’t have to be persistent, you can use 
event_base_once().</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>int</STRONG> event_base_once(<STRONG>struct</STRONG> event_base *, evutil_socket_t, <STRONG>short</STRONG>,
  <STRONG>void</STRONG> (*)(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *), <STRONG>void</STRONG> *, <STRONG>const</STRONG> <STRONG>struct</STRONG> timeval *);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>This function’s interface is the same as event_new(), except that it does not 
support EV_SIGNAL or EV_PERSIST. The scheduled event is inserted and run with 
the default priority. When the callback is finally done, Libevent frees the 
internal event structure itself. The return value is 0 on success, -1 on 
failure.</P></DIV>
<DIV class=paragraph>
<P>Events inserted with event_base_once cannot be deleted or manually activated: 
if you want to be able to cancel an event, create it with the regular 
event_new() or event_assign() interfaces.</P></DIV>
<H3 id=_manually_activating_an_event>Manually activating an event</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>Rarely, you may want to make an event active even though its conditions have 
not triggered.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>void</STRONG> event_active(<STRONG>struct</STRONG> event *ev, <STRONG>int</STRONG> what, <STRONG>short</STRONG> ncalls);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>This function makes an event <EM>ev</EM> become active with the flags 
<EM>what</EM> (a combination of EV_READ, EV_WRITE, and EV_TIMEOUT). The event 
does not need to have previously been pending, and activating it does not make 
it pending.</P></DIV>
<DIV class=paragraph>
<P>This function is defined in &lt;event2/event.h&gt;. It has existed since 
Libevent 0.3.</P></DIV>
<H3 id=_optimizing_common_timeouts>Optimizing common timeouts</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>Current versions of Libevent use a binary heap algorithm to keep track of 
pending events' timeouts. A binary heap gives performance of order O(lg n) for 
adding and deleting each event timeout. This is optimal if you’re adding events 
with a randomly distributed set of timeout values, but not if you have a large 
number of events with the same timeout.</P></DIV>
<DIV class=paragraph>
<P>For example, suppose you have ten thousand events, each of which should 
trigger its timeout five seconds after it was added. In a situation like this, 
you could get O(1) performance for each timeout by using a doubly-linked queue 
implementation.</P></DIV>
<DIV class=paragraph>
<P>Naturally, you wouldn’t want to use a queue for all of your timeout values, 
since a queue is only faster for constant timeout values. If some of the 
timeouts are more-or-less randomly distributed, then adding one of those 
timeouts to a queue would take O(n) time, which would be significantly worse 
than a binary heap.</P></DIV>
<DIV class=paragraph>
<P>Libevent lets you solve this by placing some of your timeouts in queues, and 
others in the binary heap. To do this, you ask Libevent for a special "common 
timeout" timeval, which you then use to add events having that timeval. If you 
have a very large number of events with a single common timeout, using this 
optimization should improve timeout performance.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>const</STRONG> <STRONG>struct</STRONG> timeval *event_base_init_common_timeout(
    <STRONG>struct</STRONG> event_base *base, <STRONG>const</STRONG> <STRONG>struct</STRONG> timeval *duration);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>This function takes as its arguments an event_base, and the duration of the 
common timeout to initialize. It returns a pointer to a special struct timeval 
that you can use to indicate that an event should be added to an O(1) queue 
rather than the O(lg n) heap. This special timeval can be copied or assigned 
freely in your code. It will only work with the specific base you used to 
construct it. Do not rely on its actual contents: Libevent uses them to tell 
itself which queue to use.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT>#include &lt;event2/event.h&gt;
#include &lt;string.h&gt;

<I>/* We're going to create a very large number of events on a given base,</I>
<I> * nearly all of which have a ten-second timeout.  If initialize_timeout</I>
<I> * is called, we'll tell Libevent to add the ten-second ones to an O(1)</I>
<I> * queue. */</I>
<STRONG>struct</STRONG> timeval ten_seconds = { 10, 0 };

<STRONG>void</STRONG> initialize_timeout(<STRONG>struct</STRONG> event_base *base)
{
    <STRONG>struct</STRONG> timeval tv_in = { 10, 0 };
    <STRONG>const</STRONG> <STRONG>struct</STRONG> timeval *tv_out;
    tv_out = event_base_init_common_timeout(base, &amp;tv_in);
    memcpy(&amp;ten_seconds, tv_out, <STRONG>sizeof</STRONG>(<STRONG>struct</STRONG> timeval));
}

<STRONG>int</STRONG> my_event_add(<STRONG>struct</STRONG> event *ev, <STRONG>const</STRONG> <STRONG>struct</STRONG> timeval *tv)
{
<I>    /* Note that ev must have the same event_base that we passed to</I>
<I>       initialize_timeout */</I>
    <STRONG>if</STRONG> (tv &amp;&amp; tv-&gt;tv_sec == 10 &amp;&amp; tv-&gt;tv_usec == 0)
        <STRONG>return</STRONG> event_add(ev, &amp;ten_seconds);
    <STRONG>else</STRONG>
        <STRONG>return</STRONG> event_add(ev, tv);
}</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>As with all optimization functions, you should avoid using the common_timeout 
functionality unless you’re pretty sure that it matters for you.</P></DIV>
<DIV class=paragraph>
<P>This functionality was introduced in Libevent 2.0.4-alpha.</P></DIV>
<H3 id=_telling_a_good_event_apart_from_cleared_memory>Telling a good event 
apart from cleared memory</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>Libevent provides functions that you can use to distinguish an initialized 
event from memory that has been cleared by setting it to 0 (for example, by 
allocating it with calloc() or clearing it with memset() or bzero()).</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>int</STRONG> event_initialized(<STRONG>const</STRONG> <STRONG>struct</STRONG> event *ev);

#define evsignal_initialized(ev) event_initialized(ev)
#define evtimer_initialized(ev) event_initialized(ev)</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<DIV class=title>Warning</DIV>
<P>These functions can’t reliably distinguish between an initialized event and a 
hunk of uninitialized memory. You should not use them unless you know that the 
memory in question is either cleared or initialized as an event.</P></DIV>
<DIV class=paragraph>
<P>Generally, you shouldn’t need to use these functions unless you’ve got a 
pretty specific application in mind. Events returned by event_new() are always 
initialized.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Example</DIV>
<DIV class=content><PRE><TT>#include &lt;event2/event.h&gt;
#include &lt;stdlib.h&gt;

<STRONG>struct</STRONG> reader {
    evutil_socket_t fd;
};

#define READER_ACTUAL_SIZE() \
    (<STRONG>sizeof</STRONG>(<STRONG>struct</STRONG> reader) + \
     event_get_struct_event_size())

#define READER_EVENT_PTR(r) \
    ((<STRONG>struct</STRONG> event *) (((<STRONG>char</STRONG>*)(r))+<STRONG>sizeof</STRONG>(<STRONG>struct</STRONG> reader)))

<STRONG>struct</STRONG> reader *allocate_reader(evutil_socket_t fd)
{
    <STRONG>struct</STRONG> reader *r = calloc(1, READER_ACTUAL_SIZE());
    <STRONG>if</STRONG> (r)
        r-&gt;fd = fd;
    <STRONG>return</STRONG> r;
}

<STRONG>void</STRONG> readcb(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *);
<STRONG>int</STRONG> add_reader(<STRONG>struct</STRONG> reader *r, <STRONG>struct</STRONG> event_base *b)
{
    <STRONG>struct</STRONG> event *ev = READER_EVENT_PTR(r);
    <STRONG>if</STRONG> (!event_initialized(ev))
        event_assign(ev, b, r-&gt;fd, EV_READ, readcb, r);
    <STRONG>return</STRONG> event_add(ev, NULL);
}</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The event_initialized() function has been present since Libevent 
0.3.</P></DIV>
<H3 id=_obsolete_event_manipulation_functions>Obsolete event manipulation 
functions</H3>
<DIV style="CLEAR: left"></DIV>
<DIV class=paragraph>
<P>Pre-2.0 versions of Libevent did not have event_assign() or event_new(). 
Instead, you had event_set(), which associated the event with the "current" 
base. If you had more than one base, you needed to remember to call 
event_base_set() afterwards to make sure that the event was associated with the 
base you actually wanted to use.</P></DIV>
<DIV class=listingblock>
<DIV class=title>Interface</DIV>
<DIV class=content><PRE><TT><STRONG>void</STRONG> event_set(<STRONG>struct</STRONG> event *event, evutil_socket_t fd, <STRONG>short</STRONG> what,
        <STRONG>void</STRONG>(*callback)(evutil_socket_t, <STRONG>short</STRONG>, <STRONG>void</STRONG> *), <STRONG>void</STRONG> *arg);
<STRONG>int</STRONG> event_base_set(<STRONG>struct</STRONG> event_base *base, <STRONG>struct</STRONG> event *event);</TT></PRE></DIV></DIV>
<DIV class=paragraph>
<P>The event_set() function was like event_assign(), except for its use of the 
current base. The event_base_set() function changes the base associated with an 
event.</P></DIV>
<DIV class=paragraph>
<P>There were variants of event_set() for dealing more conveniently with timers 
and signals: evtimer_set() corresponded roughly to evtimer_assign(), and 
evsignal_set() corresponded roughly to evsignal_assign().</P></DIV>
<DIV class=paragraph>
<P>Versions of Libevent before 2.0 used "signal_" as the prefix for the 
signal-based variants of event_set() and so on, rather than "evsignal_". (That 
is, they had signal_set(), signal_add(), signal_del(), signal_pending(), and 
signal_initialized().) Truly ancient versions of Libevent (before 0.6) used 
"timeout_" instead of "evtimer_". Thus, if you’re doing code archeology, you 
might see timeout_add(), timeout_del(), timeout_initialized(), timeout_set(), 
timeout_pending(), and so on.</P></DIV>
<DIV class=paragraph>
<P>In place of the event_get_fd() and event_get_signal() functions, older 
versions of Libevent (before 2.0) used two macros called EVENT_FD() and 
EVENT_SIGNAL(). These macros inspected the event structure’s contents directly 
and so prevented binary compatibility between versions; in 2.0 and later they 
are just aliases for event_get_fd() and event_get_signal().</P></DIV>
<DIV class=paragraph>
<P>Since versions of Libevent before 2.0 did not have locking support, it wasn’t 
safe to call any of the functions that change an event’s state with respect to a 
base from outside the thread running the base. These include event_add(), 
event_del(), event_active(), and event_base_once().</P></DIV>
<DIV class=paragraph>
<P>There was also an event_once() function that played the role of 
event_base_once(), but used the current base.</P></DIV>
<DIV class=paragraph>
<P>The EV_PERSIST flag did not interoperate sensibly with timeouts before 
Libevent 2.0. Instead resetting the timeout whenever the event was activated, 
the EV_PERSIST flag did nothing with the timeout.</P></DIV>
<DIV class=paragraph>
<P>Libevent versions before 2.0 did not support having multiple events inserted 
at the same time with the same fd and the same READ/WRITE. In other words, only 
one event at a time could be waiting for read on each fd, and only one event at 
a time could be waiting for write on each fd.</P></DIV></DIV></DIV>
<DIV id=footnotes>
<HR>
</DIV>
<DIV id=footer>
<DIV id=footer-text>Last updated 2011-05-12 10:36:10 EDT 
</DIV></DIV></BODY></HTML>
